#!/usr/bin/env bash
set -euo pipefail

# 框架演进同步器（底层 rsync 执行器）
# 作用：在“项目侧 ↔ 框架侧”之间同步“非私有内容”（按需）。
# 模式：
#   - verify：干跑（Dry Run）检测是否存在差异；存在则以非0退出码提示需要 apply。
#   - apply：执行实际同步（rsync），保持镜像最新。
#   - changes：输出变更的相对路径列表（用于摘要/计数）。
# 选项：
#   --no-config：遵循 No-Config 策略，跳过 config/ 目录的同步与变更统计。
# 用法示例：
#   bash scripts/sync_to_aidevflowmode.sh verify --no-config
#   bash scripts/sync_to_aidevflowmode.sh apply --no-config
#   bash scripts/sync_to_aidevflowmode.sh changes --no-config

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
AID_DIR="$(dirname "$SCRIPT_DIR")"
ROOT_DIR="$(dirname "$AID_DIR")"

# 可选配置加载：尝试从框架 config 中读取环境键（不强制）
CONFIG_ENV="$AID_DIR/config/rules.env"
if [[ -f "$CONFIG_ENV" ]]; then
  # shellcheck disable=SC1090
  source "$CONFIG_ENV" || true
fi

# 镜像目录名称仅从配置/环境获取，不设默认值
MIRROR_DIR_NAME="${MIRROR_DIR_NAME:-}"
TARGET_DIR=""
if [[ -n "$MIRROR_DIR_NAME" ]]; then
  TARGET_DIR="$ROOT_DIR/$MIRROR_DIR_NAME"
fi

MODE_ARG="${1:-verify}"
MODE="$MODE_ARG"

# Parse optional flags
if [[ $# -gt 0 ]]; then
  shift || true
fi

NO_CONFIG=false
while [[ ${1:-} ]]; do
  case "$1" in
    --no-config|--no_config)
      NO_CONFIG=true
      ;;
    *)
      # ignore unknown flags for forward compatibility
      ;;
  esac
  shift || break
done

if [[ -z "$MIRROR_DIR_NAME" ]]; then
  echo "Framework mirror name not configured (skip)"
  exit 0
fi
if [[ ! -d "$TARGET_DIR" ]]; then
  echo "Framework mirror not found: $TARGET_DIR (skip)"
  exit 0
fi

SYNC_PATHS=(
  "docs"
  "rules"
  "scripts"
  "tools/admin"
  "requirements/aidevflow_evolution_requirements.md"
)

# Respect No-Config policy when requested
if [[ "$NO_CONFIG" != "true" ]]; then
  SYNC_PATHS+=("config")
fi

RSYNC_BASE_ARGS=( -av --delete --exclude ".tmp/" --exclude ".reports/" --exclude "modules/" --exclude "api-tests/" )
RSYNC_OUT_ARGS=( -a --delete --exclude ".tmp/" --exclude ".reports/" --exclude "modules/" --exclude "api-tests/" )

changed=0

changes_output=""
for rel in "${SYNC_PATHS[@]}"; do
  SRC="$AID_DIR/$rel"
  # destination mapping: if rel is a file, map to same relative path; if dir, map dir
  if [[ -d "$SRC" ]]; then
    DEST="$TARGET_DIR/$rel"
    mkdir -p "$DEST"
    if [[ "$MODE" == "apply" ]]; then
      rsync "${RSYNC_BASE_ARGS[@]}" "$SRC/" "$DEST/"
    else
      # dry run to detect changes
      if ! rsync "${RSYNC_BASE_ARGS[@]}" --dry-run --itemize-changes "$SRC/" "$DEST/" | grep -qE "^[><ch.*]"; then
        : # no changes for this path
      else
        changed=1
        if [[ "$MODE" == "changes" ]]; then
          # output changed paths prefixed by rel/
          rsync "${RSYNC_OUT_ARGS[@]}" --dry-run --itemize-changes --out-format='%n' "$SRC/" "$DEST/" \
            | grep -vE '^\.|^\./|^building file list|^sent |^total size' \
            | grep -vE '/$' \
            | sed -E 's#^#'"$rel"'/#' >> "$SCRIPT_DIR/.tmp_changes_list"
        fi
      fi
    fi
  elif [[ -f "$SRC" ]]; then
    DEST="$TARGET_DIR/$rel"
    mkdir -p "$(dirname "$DEST")"
    if [[ "$MODE" == "apply" ]]; then
      rsync -av "$SRC" "$DEST"
    else
      if ! rsync -av --dry-run --itemize-changes "$SRC" "$DEST" | grep -qE "^[><ch.*]"; then
        :
      else
        changed=1
        if [[ "$MODE" == "changes" ]]; then
          echo "$rel" >> "$SCRIPT_DIR/.tmp_changes_list"
        fi
      fi
    fi
  fi
done

if [[ "$MODE" == "verify" ]]; then
  if [[ "$changed" -eq 1 ]]; then
    echo "Framework evolution required (non-private content changed)."
    echo "Run: bash scripts/framework_evolve.sh apply [--no-config]"
    exit 1
  else
    echo "Framework mirror is up to date (non-private content)."
  fi
fi

if [[ "$MODE" == "changes" ]]; then
  if [[ -f "$SCRIPT_DIR/.tmp_changes_list" ]]; then
    # Print deduplicated list
    sort "$SCRIPT_DIR/.tmp_changes_list" | uniq
    rm -f "$SCRIPT_DIR/.tmp_changes_list"
  fi
fi
